`begin_keywords "1364-2005"
`timescale 1ns / 1ps

`define MEM_FILENAME "H:/cva6_work/flashRCTRL/W25Q128JVxIM_V1.0_DTR/MEM.TXT"              // Memory contents file(s)
// `define MEM_ADDR_MASK 32'h00FFFFFF //24bits_addr



module tb_ahb_spi_master();

// Parameter & s
parameter BUFFER_DEPTH    = 10;
parameter AHB_ADDR_WIDTH  = 32;
parameter CLK_PERIOD      = 10;   // 100MHz
parameter NUM_PAGES = 2;
parameter PAGESIZE  = 256;

reg [7:0] memory [0:(NUM_PAGES * PAGESIZE) - 1];	                        // Main Memory Array


// DUT Signals
reg                       HCLK;
reg                       HRESETn;
reg  [AHB_ADDR_WIDTH-1:0] HADDR;
reg  [2:0]                HBURST;
reg  [2:0]                HSIZE;
reg  [2:0]                HTRANS;
reg  [31:0]               HWDATA;
reg                       HWRITE;
wire [31:0]               HRDATA;
wire                      HREADY;
wire                      HRESP;

wire                      events_o;

wire                      spi_clk;
wire                      spi_csn0;
wire                      spi_csn1;
wire                      spi_csn2;
wire                      spi_csn3;
wire                      spi_sdo0;
wire                      spi_sdo1;
wire                      spi_sdo2;
wire                      spi_sdo3;
wire                      spi_oe0;
wire                      spi_oe1;
wire                      spi_oe2;
wire                      spi_oe3;
wire                      spi_sdi0;
wire                      spi_sdi1;
wire                      spi_sdi2;
wire                      spi_sdi3;
  // AHB传输类型定义
  localparam [1:0] 
    HTRANS_IDLE   = 2'b00,
    HTRANS_BUSY   = 2'b01,
    HTRANS_NONSEQ = 2'b10,
    HTRANS_SEQ    = 2'b11;

  // 突发类型定义
  localparam [2:0]
    HBURST_SINGLE = 3'b000,
    HBURST_INCR   = 3'b001,
    HBURST_WRAP4  = 3'b010,
    HBURST_INCR4  = 3'b011,
    HBURST_WRAP8  = 3'b100,
    HBURST_INCR8  = 3'b101,
    HBURST_WRAP16 = 3'b110,
    HBURST_INCR16 = 3'b111;

// Testbench Variables
reg [31:0] read_data;
integer test_case;

// 实例化模块的显式连接
ahb_spi_master #(
    .BUFFER_DEPTH(BUFFER_DEPTH),
    .AHB_ADDR_WIDTH(AHB_ADDR_WIDTH)
) dut (
    // AHB 接口
    .HCLK       (HCLK),
    .HRESETn    (HRESETn),
    .HADDR      (HADDR),
    .HBURST     (HBURST),
    .HSIZE      (HSIZE),
    .HTRANS     (HTRANS),
    .HWDATA     (HWDATA),
    .HWRITE     (HWRITE),
    .HRDATA     (HRDATA),
    .HREADY     (HREADY),
    .HRESP      (HRESP),

    // 事件接口
    .events_o   (events_o),

    // SPI 主设备接口
    .spi_clk    (spi_clk),
    .spi_csn0   (spi_csn0),
    .spi_csn1   (spi_csn1),
    .spi_csn2   (spi_csn2),
    .spi_csn3   (spi_csn3),
    .spi_sdo0   (spi_sdo0),
    .spi_sdo1   (spi_sdo1),
    .spi_sdo2   (spi_sdo2),
    .spi_sdo3   (spi_sdo3),
    .spi_oe0    (spi_oe0),
    .spi_oe1    (spi_oe1),
    .spi_oe2    (spi_oe2),
    .spi_oe3    (spi_oe3),
    .spi_sdi0   (spi_sdi0),
    .spi_sdi1   (spi_sdi1),
    .spi_sdi2   (spi_sdi2),
    .spi_sdi3   (spi_sdi3)
);

// Clock Generation
always #(CLK_PERIOD/2) HCLK = ~HCLK;

// // Reset Generation
// initial begin
//     HCLK = 0;
//     HRESETn = 0;
//     #100;
//     HRESETn = 1;
// end
wire [3:0] qspi_io;
  // 实例化 Flash 模型
  W25Q128JVxIM flash (
    .CSn   (spi_csn0),          // 片选
    .CLK   (spi_clk),         // 时钟
    .DIO   (qspi_io[0]),       // IO0（双向）
    .DO    (qspi_io[1]),       // IO1（双向）
    .WPn   (qspi_io[2]),       // IO2（双向）
    .HOLDn (qspi_io[3])        // IO3（双向）
  );

assign qspi_io[0] = spi_oe0 ? spi_sdo0 : 1'bz;
assign qspi_io[1] = spi_oe1 ? spi_sdo1 : 1'bz;
assign qspi_io[2] = spi_oe2 ? spi_sdo2 : 1'bz;
assign qspi_io[3] = spi_oe3 ? spi_sdo3 : 1'bz;

assign spi_sdi0 = qspi_io[0];
assign spi_sdi1 = qspi_io[1];
assign spi_sdi2 = qspi_io[2];
assign spi_sdi3 = qspi_io[3];




task ahb_read(
  input [AHB_ADDR_WIDTH-1:0] addr,  // 地址
  input [2:0]                size,  // 传输大小：3'b000=8bit, 3'b001=16bit, 3'b010=32bit
  input [31:0]               expected_data  // 外部传入的预期数据
);
    reg [31:0] data_mask;
  begin
    //////////////////////////////////////////////////
    // Phase 1: 地址传输阶段
    //////////////////////////////////////////////////
    @(posedge HCLK);
    HADDR   = addr;           // 设置地址
    HTRANS  = HTRANS_NONSEQ;
    HWRITE  = 1'b0;           // 读操作
    HSIZE   = size;           // 根据输入参数设置传输大小
    HBURST  = HBURST_SINGLE;  // 单次突发

    // 等待地址阶段完成
    begin : wait_address_phase
      forever begin
        @(posedge HCLK);
        if (HREADY === 1'b1) begin
          disable wait_address_phase;
        end
      end
    end

    //////////////////////////////////////////////////
    // Phase 2: 数据传输阶段
    //////////////////////////////////////////////////
    HTRANS = HTRANS_IDLE;     // 结束传输

    // 等待数据阶段完成
    begin : wait_data_phase
      forever begin
        @(posedge HCLK);
        if (HREADY === 1'b1) begin
          disable wait_data_phase;
        end
      end
    end

    //////////////////////////////////////////////////
    // Phase 3: 数据采样与验证
    //////////////////////////////////////////////////
    @(negedge HCLK);
    read_data = HRDATA;       // 读取数据

    // 根据传输大小生成掩码（可选）

    case(size)
      3'b000: data_mask = 32'h000000FF; // 8-bit 掩码
      3'b001: data_mask = 32'h0000FFFF; // 16-bit 掩码
      3'b010: data_mask = 32'hFFFFFFFF; // 32-bit 掩码
      default: data_mask = 32'hFFFFFFFF;
    endcase

    // 检查数据（带掩码）
    if ((read_data & data_mask) === (expected_data & data_mask)) begin
      $display("PASS: Addr 0x%h, Size %0d-bit, Data=0x%h (Masked:0x%h)", 
               addr, (8<<size), read_data, data_mask);
    end else begin
      $display("FAIL: Addr 0x%h, Size %0d-bit, Exp=0x%h, Got=0x%h (Masked:0x%h)", 
               addr, (8<<size), expected_data, read_data, (read_data & data_mask));
    end
  end
endtask

// 定义全局预期数据存储器（替代任务参数中的数组）
reg [31:0] expected_mem [0:15];  // 外部定义的存储器

  integer byte_addr; // 假设1:1地址映射
  integer mem_index;
  integer a;
task ahb_burst_read(
  input [AHB_ADDR_WIDTH-1:0] start_addr,
  input [2:0]                burst_type,
  input [2:0]                size
);
  // 局部变量声明
  integer i;
  integer beat_count;
  reg [31:0] expected_array; // 从memory组合的预期数据
  reg [AHB_ADDR_WIDTH-1:0] current_addr;
  reg [31:0] data_mask;
  reg [AHB_ADDR_WIDTH-1:0] expected_index;
  reg error_flag;  // 错误标志
  begin
    current_addr = start_addr;
    expected_index = 0;
    error_flag = 0;  // 初始无错误

    // 计算传输次数
    case(burst_type)
      HBURST_SINGLE : beat_count = 1;
      HBURST_INCR4  : beat_count = 4;
      HBURST_INCR8  : beat_count = 8;
      HBURST_INCR16 : beat_count = 16;
      HBURST_WRAP4  : beat_count = 4;
      HBURST_WRAP8  : beat_count = 8;
      HBURST_WRAP16 : beat_count = 16;
      default: begin
        $display("ERROR: Unsupported burst type");
        $finish;
      end
    endcase

    // 生成数据掩码
    case(size)
      3'b000: data_mask = 32'h000000FF; // 8-bit
      3'b001: data_mask = 32'h0000FFFF; // 16-bit
      3'b010: data_mask = 32'hFFFFFFFF; // 32-bit
      default: data_mask = 32'hFFFFFFFF;
    endcase

    //////////////////////////////////////////////////
    // Phase 1: 启动第一个地址阶段
    //////////////////////////////////////////////////
    @(posedge HCLK);
    HADDR   = current_addr;
    HTRANS  = HTRANS_NONSEQ;
    HSIZE   = size;
    HBURST  = burst_type;
    HWRITE  = 1'b0;

    // 等待地址阶段完成
    begin : wait_addr_phase_1
      forever begin
        @(posedge HCLK);
        if (HREADY === 1'b1) disable wait_addr_phase_1;
      end
    end
    #1
    //////////////////////////////////////////////////
    // Phase 2: 流水线处理后续传输
    //////////////////////////////////////////////////
    for (i=1; i<beat_count; i=i+1) begin:after_addr



      // 启动下一个地址阶段

      byte_addr = current_addr & 32'h00FFFFFF; // 假设1:1地址映射
      current_addr = get_next_address(current_addr, burst_type, size);

            // 计算memory索引（AHB地址直接映射到memory字节地址）

      // 组合预期数据（根据传输大小）
      case(size)
        3'b000: begin // 8-bit
          mem_index = byte_addr;
          expected_array = {24'b0, memory[mem_index]};
        end
        3'b001: begin // 16-bit
          mem_index = byte_addr;
          expected_array = {16'b0, memory[mem_index+1], memory[mem_index]};
        end
        3'b010: begin // 32-bit
          mem_index = byte_addr;
          expected_array = {memory[mem_index+3], memory[mem_index+2], 
                          memory[mem_index+1], memory[mem_index]};
        end
      endcase


      //@(posedge HCLK);
     // #1
      HADDR  = current_addr;
      HTRANS = HTRANS_SEQ;

      // 等待数据阶段并验证
      begin : wait_data_phase
        forever begin
          @(posedge HCLK);
          if (HREADY === 1'b1) begin
            #1
           // @(negedge HCLK);
            // 如果是最后一个地址阶段，设置HTRANS=IDLE
            if (i == beat_count-1) begin
              //下一个周期生效可能不太友好，应该本周期完就好，但是如果本周期马上切换，会导致无法锁存到的问题（仿真顺序的问题
              //改成延时
              //@(posedge HCLK); // 下一周期生效
              HTRANS = HTRANS_IDLE;
            end
            // 检查数据
            if ((HRDATA & data_mask) === (expected_array & data_mask)) begin
              $display("PASS: Beat %0d, Addr 0x%h, Data=0x%h (Masked:0x%h)",
                       expected_index, current_addr, HRDATA, (HRDATA & data_mask));
            end else begin
              $display("FAIL: Beat %0d, Addr 0x%h, Exp=0x%h, Got=0x%h (Masked:0x%h)",
                       expected_index, current_addr, expected_array, HRDATA, (HRDATA & data_mask));
              error_flag = 1;  // 标记错误
            end
            expected_index = expected_index + 1;
            disable wait_data_phase;
          end
        end
      end
    end

    //////////////////////////////////////////////////
    // Phase 3: 处理最后一个数据阶段
    //////////////////////////////////////////////////
    begin : wait_final_data
      forever begin
        @(posedge HCLK);
        if (HREADY === 1'b1) begin
         #1;
          // 计算当前的byte_addr和expected_array
          byte_addr = current_addr & 32'h00FFFFFF; // 假设1:1地址映射
          case(size)
            3'b000: begin // 8-bit
              mem_index = byte_addr;
              expected_array = {24'b0, memory[mem_index]};
            end
            3'b001: begin // 16-bit
              mem_index = byte_addr;
              expected_array = {16'b0, memory[mem_index+1], memory[mem_index]};
            end
            3'b010: begin // 32-bit
              mem_index = byte_addr;
              expected_array = {memory[mem_index+3], memory[mem_index+2], 
                              memory[mem_index+1], memory[mem_index]};
            end
          endcase

          @(negedge HCLK);
          if ((HRDATA & data_mask) === (expected_array & data_mask)) begin
            $display("PASS: Beat %0d, Addr 0x%h, Data=0x%h (Masked:0x%h)",
                     expected_index, current_addr, HRDATA, (HRDATA & data_mask));
          end else begin
            $display("FAIL: Beat %0d, Addr 0x%h, Exp=0x%h, Got=0x%h (Masked:0x%h)",
                     expected_index, current_addr, expected_array, HRDATA, (HRDATA & data_mask));
            error_flag = 1;
          end
          disable wait_final_data;
        end
      end
    end

    // 传输结束
    HTRANS = HTRANS_IDLE;

    // 输出突发传输总结
    if (error_flag === 0) begin
      $display("Burst PASS: %0d beats, Addr 0x%h to 0x%h", 
               beat_count, start_addr, current_addr);
    end else begin
      $display("Burst FAIL: %0d beats, Check error logs", beat_count);
    end
  end
endtask

task ahb_burst_delay_read(
  input [AHB_ADDR_WIDTH-1:0] start_addr,
  input [2:0]                burst_type,
  input [2:0]                size
);
  // 局部变量声明（保持原样）
  integer i;
  integer beat_count;
  reg [31:0] expected_array;
  reg [AHB_ADDR_WIDTH-1:0] current_addr;
  reg [31:0] data_mask;
  reg [AHB_ADDR_WIDTH-1:0] expected_index;
  reg error_flag;
  begin
    current_addr = start_addr;
    expected_index = 0;
    error_flag = 0;
    // beat_count计算（保持原样）
    case(burst_type)
      HBURST_SINGLE : beat_count = 1;
      HBURST_INCR4  : beat_count = 4;
      HBURST_INCR8  : beat_count = 8;
      HBURST_INCR16 : beat_count = 16;
      HBURST_WRAP4  : beat_count = 4;
      HBURST_WRAP8  : beat_count = 8;
      HBURST_WRAP16 : beat_count = 16;
      default: begin
        $display("ERROR: Unsupported burst type");
        $finish;
      end
    endcase
    // 数据掩码计算（保持原样）
    data_mask = get_data_mask(size);
    @(posedge HCLK);

    HSIZE   = size;
    HBURST  = burst_type;
    HWRITE  = 1'b0;

    HTRANS = HTRANS_IDLE;
    for (i=0; i<beat_count; i=i+1) begin: data_phase_loop
    HTRANS  = i == 0 ? HTRANS_NONSEQ : HTRANS_SEQ;
    HADDR   = current_addr;
    
    // 等待地址阶段完成
    begin : wait_addr_phase
      forever begin
        @(posedge HCLK);
        if (HREADY === 1'b1 && (HTRANS === HTRANS_NONSEQ || HTRANS==HTRANS_SEQ)) disable wait_addr_phase;
      end
    end
    HTRANS = HTRANS_IDLE;

      // 计算当前数据预期值
      byte_addr = current_addr & 32'h00FFFFFF; // 地址映射
      case(size)
        3'b000: begin
          mem_index = byte_addr;
          expected_array = {24'b0, memory[mem_index]};
        end
        3'b001: begin
          mem_index = byte_addr;
          expected_array = {16'b0, memory[mem_index+1], memory[mem_index]};
        end
        3'b010: begin
          mem_index = byte_addr;
          expected_array = {memory[mem_index+3], memory[mem_index+2],
                          memory[mem_index+1], memory[mem_index]};
        end
      endcase


      // 等待数据阶段完成并验证
      begin : wait_data_phase
        forever begin
          @(posedge HCLK);
          if (HREADY === 1'b1) begin
            #1;
            // 数据验证（保持原样）
            if ((HRDATA & data_mask) === (expected_array & data_mask)) begin
              $display("PASS: Beat %0d, Addr 0x%h, Data=0x%h (Masked:0x%h)",
                       expected_index, current_addr, HRDATA, (HRDATA & data_mask));
            end else begin
              $display("FAIL: Beat %0d, Addr 0x%h, Exp=0x%h, Got=0x%h (Masked:0x%h)",
                       expected_index, current_addr, expected_array, HRDATA, (HRDATA & data_mask));
              error_flag = 1;
            end
            expected_index = expected_index + 1;
 
            HTRANS = HTRANS_IDLE;
            HADDR  = current_addr;
            repeat(4) @(posedge HCLK); // 插入4周期等待

            disable wait_data_phase;
          end
        end
      end
      // 准备下一地址阶段
      if (i != beat_count -1)
        current_addr = get_next_address(current_addr, burst_type, size);            
    end

    //////////////////////////////////////////////////
    // 传输结束处理（保持原样）
    //////////////////////////////////////////////////
    if (error_flag === 0) begin
      $display("Burst PASS: %0d beats, Addr 0x%h to 0x%h",
               beat_count, start_addr, current_addr);
    end else begin
      $display("Burst FAIL: %0d beats, Check error logs", beat_count);
    end
  end


endtask          

task ahb_single_transfer(
  input                     is_write,
  input [AHB_ADDR_WIDTH-1:0] addr,
  input [2:0]               size,
  input [31:0]              wr_data,
  output [31:0]              rd_data
);
  reg [31:0] data_mask;
  begin
    // 步骤1：参数初始化
    data_mask = get_data_mask(size);
    
    // 地址对齐检查（保留必要的协议检查）
    if ((size == 3'b001 && addr[0] != 0) ||  // 16bit对齐检查
        (size == 3'b010 && addr[1:0] != 0)) 
    begin
      $display("[%0t] ERROR: Address alignment error! Addr=0x%h Size=%0d",
              $time, addr, 1 << size);
      $finish;
    end

    // 步骤2：地址阶段
    @(posedge HCLK);
    //需要使用非阻塞赋值
    HADDR  <= addr;
    HSIZE  <= size;
    HBURST <= HBURST_SINGLE;
    HWRITE <= is_write;
    HTRANS <= HTRANS_NONSEQ;
    
    HWDATA <= wr_data & data_mask;  // 写操作驱动数据

    // 等待地址阶段完成
    while (~(HREADY == 1'b1 && HTRANS == HTRANS_NONSEQ)) begin
      @(posedge HCLK);
    end
    // #0//争用问题，不加不行
    HTRANS <= HTRANS_IDLE;
    HWRITE <= 1'b1;

    // 步骤3：简化数据阶段
    while (HREADY !== 1'b1) begin
      @(posedge HCLK);
    end
    
    // 读操作处理
    rd_data <= HRDATA & data_mask;  // 获取数据并输出

    // 步骤4：清理阶段
    @(posedge HCLK);
    HTRANS <= HTRANS_IDLE;
    HWDATA <= 'hz;
  end
endtask
task ahb_burst_delay_write(
  input [AHB_ADDR_WIDTH-1:0] start_addr,
  input [2:0]                burst_type,
  input [2:0]                size
);
  // 局部变量声明
  integer i;
  integer beat_count;
  reg [AHB_ADDR_WIDTH-1:0] current_addr;
  reg [31:0]               write_data;
  reg [2:0]                saved_size;
  
  begin
    current_addr <= start_addr;
    saved_size <= size;
    
    // Beat数量计算（仅支持SINGLE/INCR）
    case(burst_type)
      HBURST_SINGLE : beat_count = 1;
      HBURST_INCR4  : beat_count = 4;
      HBURST_INCR8  : beat_count = 8;
      HBURST_INCR16 : beat_count = 16;
      default: begin
        $display("ERROR: Unsupported burst type");
        $finish;
      end
    endcase

    @(posedge HCLK);
    // 控制信号设置
    HSIZE   <= saved_size;
    HBURST  <= burst_type;
    HWRITE  <= 1'b1;  // 写操作
    HTRANS  <= HTRANS_IDLE;

    for (i=0; i<beat_count; i=i+1) begin
      // 地址阶段控制
      HTRANS <= (i == 0) ? HTRANS_NONSEQ : HTRANS_SEQ;
      HADDR  <= current_addr;

      // 等待地址阶段完成
      begin : wait_addr_phase
        forever begin
          @(posedge HCLK);
          if (HREADY === 1'b1 && (HTRANS === HTRANS_NONSEQ || HTRANS === HTRANS_SEQ)) 
            disable wait_addr_phase;
        end
      end
      
      // 数据准备阶段
      HTRANS <= HTRANS_IDLE;
      byte_addr = current_addr & 32'h00FFFFFF; // 地址映射
      
      // 从ts_mem提取数据（小端模式）
      case(saved_size)
        3'b000: begin // Byte
          mem_index = byte_addr;
          write_data = {24'b0, memory[mem_index]};
        end
        3'b001: begin // Halfword
          mem_index = byte_addr;
          write_data = {16'b0, memory[mem_index+1], memory[mem_index]};
        end
        3'b010: begin // Word
          mem_index = byte_addr;
          write_data = {memory[mem_index+3], memory[mem_index+2],
                       memory[mem_index+1], memory[mem_index]};
        end
        default: write_data = 32'h0;
      endcase
      
      // 驱动写数据
      HWDATA <= write_data & 32'hFFFF_FF00;
      
      // 等待数据阶段完成
      begin : wait_data_phase
        forever begin
          @(posedge HCLK);
          if (HREADY === 1'b1) begin
            #1;
            $display("WRITE: Beat %0d, Addr 0x%h, Data=0x%h",
                     i, current_addr, HWDATA);
            // 插入与read相同的延迟
            repeat(4) @(posedge HCLK);
            disable wait_data_phase;
          end
        end
      end

      // 更新下一地址（排除最后一次传输）
      if (i != beat_count-1)
        current_addr = get_next_address(current_addr, burst_type, saved_size);
    end
    
    // 结束状态报告
    $display("Burst WRITE Completed: %0d beats, Start=0x%h, End=0x%h",
             beat_count, start_addr, current_addr);
  end
endtask

// 保留数据掩码函数（仍用于总线驱动）
function [31:0] get_data_mask(input [2:0] size);
  case(size)
    3'b000: get_data_mask = 32'h000000FF;
    3'b001: get_data_mask = 32'h0000FFFF;
    3'b010: get_data_mask = 32'hFFFFFFFF;
    default: get_data_mask = 32'hFFFFFFFF;
  endcase
endfunction
// 地址计算函数（支持INCR4和WRAP4）
function [AHB_ADDR_WIDTH-1:0] get_next_address(
  input [AHB_ADDR_WIDTH-1:0] current_addr,
  input [2:0]                burst_type,
  input [2:0]                size
);
  reg [AHB_ADDR_WIDTH-1:0] next_addr;
  reg [AHB_ADDR_WIDTH-1:0] wrap_boundary;
  begin
    case(burst_type)
    HBURST_SINGLE: next_addr = current_addr; // 单次传输地址不变
    HBURST_INCR4,
    HBURST_INCR8,
    HBURST_INCR16: 
        next_addr = current_addr + (1 << size); // 地址递增
        



      // WRAP类型
      HBURST_WRAP4,
      HBURST_WRAP8,
      HBURST_WRAP16: 
        begin
          // 计算WRAP4回绕边界（示例：4次传输，地址按4*size字节回绕）
          case(burst_type)
            HBURST_WRAP4: wrap_boundary = 4 * (1 << size);
            HBURST_WRAP8: wrap_boundary = 8 * (1 << size);
            HBURST_WRAP16:wrap_boundary = 16 * (1 << size);
          endcase
            next_addr = (current_addr / wrap_boundary) * wrap_boundary + 
                        ((current_addr + (1 << size)) % wrap_boundary);
        end
      default: 
        next_addr = current_addr;
    endcase
    get_next_address = next_addr;
  end
endfunction

localparam 
SECTOR_ERASE_INST= 32'h20000000,
WRITE_ENABLE_INST= 32'h06000000,
REG_STATUS = 32'h00,// BASEREG + 0x00
REG_CLKDIV = 32'h04,// BASEREG + 0x04
REG_SPICMD = 32'h08,// BASEREG + 0x08
REG_SPIADR = 32'h0C,// BASEREG + 0x0C
REG_SPILEN = 32'h10,// BASEREG + 0x10
REG_SPIDUM = 32'h14,// BASEREG + 0x14
REG_TXFIFO = 32'h18,// BASEREG + 0x18
REG_RXFIFO = 32'h20,// BASEREG + 0x20
REG_INTCFG = 32'h24,// BASEREG + 0x24
REG_INTSTA = 32'h28,// BASEREG + 0x28
WRITE = 1'b1,
READ  = 1'b0,
SIZE_1B = 3'b000,
SIZE_2B = 3'b001,
SIZE_4B = 3'b010,
ERASE_ADDR=32'h0000_0000,
ERASE_LEN =32'h0000_1808,//data_len,addr_len,cmd_len
WEL_LEN   =32'h0000_0008,//data_len,addr_len,cmd_len
STATUS_REG_SET=32'h0000_0104;


reg [31:0] ahb_rd_data;
// 主测试流程
initial begin
  // 初始化
  //read same file for flahs init
 $readmemh(`MEM_FILENAME,memory);

  HADDR   = 0;
  HTRANS  = HTRANS_IDLE;
  HWRITE  = 0;
  HSIZE   = 0;
  HBURST  = 0;

  HCLK    = 0;
  HRESETn = 0;
  // 复位释放
  #100;
  HRESETn = 1;
  repeat(2) @(posedge HCLK);

#100;




  //write QSPI reg
//write enable inst
ahb_single_transfer(WRITE,REG_SPICMD,SIZE_4B,WRITE_ENABLE_INST,ahb_rd_data);
ahb_single_transfer(WRITE,REG_SPILEN,SIZE_4B,WEL_LEN,ahb_rd_data);
ahb_single_transfer(WRITE,REG_STATUS,SIZE_4B,STATUS_REG_SET,ahb_rd_data);
ahb_burst_delay_write(32'h4000_0000, HBURST_INCR4, 3'b010);

//   //to ERASE flash
// ahb_single_transfer(WRITE,REG_SPICMD,SIZE_4B,SECTOR_ERASE_INST,ahb_rd_data);
// //set flash addr
// ahb_single_transfer(WRITE,REG_SPIADR,SIZE_4B,ERASE_ADDR,ahb_rd_data);
// //set data addr cmd len
// ahb_single_transfer(WRITE,REG_SPILEN,SIZE_4B,ERASE_LEN,ahb_rd_data);
// //因为没有 dummy 可以不需要设置
// //clk_div 默认是0好像也可以不用设置
// //接下来就是设置状态寄存器寄存器了
// ahb_single_transfer(WRITE,REG_STATUS,SIZE_4B,STATUS_REG_SET,ahb_rd_data);

// #35000000;

#3000000;

  // 测试案例1：32-bit 读取（全0xFF）
  ahb_burst_delay_read(32'h4000_0000, HBURST_SINGLE, 3'b010);
  ahb_burst_delay_read(32'h4000_0004, HBURST_SINGLE, 3'b010);
  ahb_burst_delay_read(32'h4000_0020, HBURST_SINGLE, 3'b010);




  // 测试案例1：32-bit INCR4突发（全0xFF）
  expected_mem[0] = 32'hCCDDEEFF;
  expected_mem[1] = 32'hFFFFFFFF;
  expected_mem[2] = 32'hFFFFFFFF;
  expected_mem[3] = 32'hFCFDFEFF;
  expected_mem[4] = 32'hFFFFFFFF;
  expected_mem[5] = 32'hFFFFFFFF; 
  expected_mem[6] = 32'hFFFFFFFF;
  expected_mem[7] = 32'hFFFFFFFF;
  ahb_burst_delay_read(32'h4000_0000, HBURST_INCR8, 3'b010);

  // 测试案例2：16-bit WRAP4突发（自定义数据）
  expected_mem[0] = 32'h0000FFFF;
  expected_mem[1] = 32'h0000FFFF;
  expected_mem[2] = 32'h0000FFFF;
  expected_mem[3] = 32'h0000FFFF;

  ahb_burst_delay_read(32'h4000_0030, HBURST_WRAP4, 3'b001);
  ahb_burst_delay_read(32'h4000_0000, HBURST_INCR8, 3'b010);
  // // 测试案例1：32-bit 读取（全0xFF）
  // ahb_read(32'h4000_0000, 3'b010, 32'hCCDDEEFF);



  // // 测试案例2：16-bit 读取（低16位为0xFFFF）
  // ahb_read(32'h4000_0004, 3'b001, 32'h0000FFFF);

  // // 测试案例3：8-bit 读取（最低字节为0xFF）
  // ahb_read(32'h4000_0006, 3'b000, 32'h000000FF);

  // ahb_read(32'h4000_0000, 3'b001, 32'h0000EEFF);

  $finish;
end


endmodule

`end_keywords